using System;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using System.Threading;

namespace Project
{
    class Drivers
    {
        private static Drivers instance;

        private OutputPort mled_kitchen;
        private OutputPort mled_living;
        private OutputPort mled_bedroom;
        private OutputPort mled_bathroom;

        private InputPort mwindow_kitchen;
        private InputPort mwindow_living;
        private InputPort mwindow_bedroom;
        private InputPort mwindow_bathroom;

        private OutputPort mled_irrigation;

        //Temperature
        private const ushort address = 79;
        private const int clockRateKHz = 100;
        I2CDevice device;
        private OutputPort mled_heating;
        private OutputPort mled_AC;

        //Rules
        private string light_rules;
        private string irrigation_rules;
        private string temp_rules;

        //Notification
        private string registrationID;
        private string authKey;
        private string WPUri;
        bool alert;

        private Drivers()
        {
            //Lights
            mled_kitchen = new OutputPort(DeviceSolutions.SPOT.Hardware.TahoeII.Pins.SW1, false);
            mled_living = new OutputPort(DeviceSolutions.SPOT.Hardware.TahoeII.Pins.SW2, false);
            mled_bedroom = new OutputPort(DeviceSolutions.SPOT.Hardware.TahoeII.Pins.SW3, false);
            mled_bathroom = new OutputPort(DeviceSolutions.SPOT.Hardware.TahoeII.Pins.SW4, false);

            //Windows
            mwindow_kitchen = new InputPort(DeviceSolutions.SPOT.Hardware.TahoeII.Pins.SW5, false, Port.ResistorMode.PullUp);
            mwindow_living = new InputPort(DeviceSolutions.SPOT.Hardware.TahoeII.Pins.SW6, false, Port.ResistorMode.PullUp);
            mwindow_bedroom = new InputPort(DeviceSolutions.SPOT.Hardware.TahoeII.Pins.SW8, false, Port.ResistorMode.PullUp);
            mwindow_bathroom = new InputPort(DeviceSolutions.SPOT.Hardware.TahoeII.Pins.SW9, false, Port.ResistorMode.PullUp);

            //Irrigation
            mled_irrigation = new OutputPort(DeviceSolutions.SPOT.Hardware.TahoeII.Pins.SW7, false);

            //Temperature
            I2CDevice.Configuration config = new I2CDevice.Configuration(address, clockRateKHz);
            device = new I2CDevice(config);
            mled_heating = new OutputPort(DeviceSolutions.SPOT.Hardware.Meridian.Pins.GPIO10, false);
            mled_AC = new OutputPort(DeviceSolutions.SPOT.Hardware.Meridian.Pins.GPIO11, false);

            light_rules = "";
            irrigation_rules = "";
            temp_rules = "";

            //Notification
            alert = true;
            registrationID = "APA91bGKwFwsS1Sb22F9YRVEDFvKPZ4w0S1stCQRKMmpCfd0Qk-RHHlWlKqLLOlP5JbhH250n14yE3QAdJH_N5qOfAtOKUHd0wU6D9BDbby16BXaX6iACmwsX7S0BpRTRLehhrvJLN3E";
            WPUri = "http://db3.notify.live.net/throttledthirdparty/01.00/AAFB_g1JWCmoR4mW7M7zrx_xAgAAAAADAQAAAAQUZm52OjIzOEQ2NDJDRkI5MEVFMEQ";
            authKey = "AIzaSyA_tSIEcPuHZkSdAR-zc6x4YiZn8E1v0u0";
        }

        public static void createInstance()
        {
            instance = new Drivers();
        }

        public static Drivers getInstance()
        {
            return instance;
        }

        public double getTemperature()
        {

            byte[] inBuffer = new byte[2];
            I2CDevice.I2CReadTransaction readTransaction = I2CDevice.CreateReadTransaction(inBuffer);

            //execute both transactions
            I2CDevice.I2CTransaction[] transactions = new I2CDevice.I2CTransaction[] { readTransaction };

            Thread.Sleep(1000);

            int transferred = device.Execute(transactions, 100);

            double absolute_value = (inBuffer[0] << 1) >> 1;
            if (inBuffer[0] >> 7 == 1)
                absolute_value = -absolute_value;

            if (inBuffer[1] >> 7 == 1)
                absolute_value += 0.5;

            return absolute_value;
        }

        public void deleteLightRules(string guid)
        {
            try{
            string updated_rules=light_rules.Substring(0,light_rules.IndexOf(guid));
            string rest = light_rules.Substring(light_rules.IndexOf(guid));
            if (rest.IndexOf('|')!=-1)
                updated_rules += rest.Substring(rest.IndexOf('|')+1);

            light_rules = updated_rules;
            }
            catch
            {
                Debug.Print("The rule does not exist");
            }
        }

        public void deleteIrrigationRules(string guid)
        {
            try
            {
                string updated_rules = irrigation_rules.Substring(0, irrigation_rules.IndexOf(guid));
                string rest = irrigation_rules.Substring(irrigation_rules.IndexOf(guid));
                if (rest.IndexOf('|') != -1)
                    updated_rules += rest.Substring(rest.IndexOf('|') + 1);

                irrigation_rules = updated_rules;
            }
            catch
            {
                Debug.Print("The rule does not exist");
            }
        }

        
        public OutputPort led_kitchen
        {
            get { return mled_kitchen; }
            set { mled_kitchen = value; }
        }

        public OutputPort led_living
        {
            get { return mled_living; }
            set { mled_living = value; }
        }

        public OutputPort led_bedroom
        {
            get { return mled_bedroom; }
            set { mled_bedroom = value; }
        }

        public OutputPort led_bathroom
        {
            get { return mled_bathroom; }
            set { mled_bathroom = value; }
        }

        public InputPort window_kitchen
        {
            get { return mwindow_kitchen; }
            set { mwindow_kitchen = value; }
        }

        public InputPort window_living
        {
            get { return mwindow_living; }
            set { mwindow_living = value; }
        }

        public InputPort window_bedroom
        {
            get { return mwindow_bedroom; }
            set { mwindow_bedroom = value; }
        }

        public InputPort window_bathroom
        {
            get { return mwindow_bathroom; }
            set { mwindow_bathroom = value; }
        }

        public OutputPort led_irrigation
        {
            get { return mled_irrigation; }
            set { mled_irrigation = value; }
        }

        public OutputPort led_heating
        {
            get { return mled_heating; }
            set { mled_heating = value; }
        }

        public OutputPort led_AC
        {
            get { return mled_AC; }
            set { mled_AC = value; }
        }

        public string lightRules
        {
            get { return light_rules; }
            set
            {
                if (light_rules == "")
                {
                    light_rules = value;
                }
                else
                {
                    light_rules += ("|" + value);
                }
            }
        }

        public string irrigationRules
        {
            get { return irrigation_rules; }
            set 
            {
                if (irrigation_rules == "")
                {
                    irrigation_rules = value;
                }
                else
                {
                    irrigation_rules += ("|" + value);
                }
            
            }
        }

        public string tempRules
        {
            get { return temp_rules; }
            set { temp_rules = value; }
        }

        public string AuthKey
        {
            get { return authKey; }
            set { authKey = value; }
        }

        public string RegitrationID
        {
            get { return registrationID; }
            set
            {
                if (registrationID == "")
                    registrationID = value;
                else
                {
                    if (registrationID.IndexOf(value) == -1)
                        registrationID += "|" + value;
                }
            }
        }

        public string WindowsPhoneUri
        {
            get { return WPUri; }
            set
            {
                if (WPUri == "")
                    WPUri = value;
                else
                {
                    if (WPUri.IndexOf(value) == -1)
                        WPUri += "|" + value;
                }
            }
        }

        public bool Alert
        {
            get { return alert; }
            set { alert = value; }
        }
    }
}
